function [ U, theta, V, obj ] = PostProcess( U, V, D, type )

[row, col, val] = find(D);
K = size(U, 2);

if(type == 1)
    M = zeros(length(val), K);

    for k = 1:K
        uk = U(:, k);
        vk = V(:, k);
        Mk = partXY(uk', vk', row, col, length(row));

        M(:, k) = Mk';
    end

    theta = pinv(M'*M)*(M'*val);
    
    obj = val - M*theta;
    obj = 0.5*sum(obj(:).^2);
    
    theta = diag(theta);
elseif(type == 2)
    X = randn(K, K);
    lb = -1e+9*ones(size(X));
    ub = +1e+9*ones(size(X));

    % max number of iterations
    param.maxIter = 1000;    
    % max number of calling the function
    param.maxFnCall = 1000;  
    % tolerance of constraint satisfaction
    param.relCha = 1e+5;      
    % final objective function accuracy parameter
    param.tolPG = 1e-2;   
    % stored gradients
    param.m = 1;
    
    grad = sparse(row, col, val, size(D,1), size(D,2));

    callfunc = @(S) bgfsPost( S, row, col, val, U, V, grad );

    [theta, obj, iter, numCall, flag] = lbfgsb(X,lb,ub,callfunc, [], [], param);
    
    obj = partXY((U*theta)', V', row, col, length(row));
    obj = obj' - val;
    obj = 0.5*sum(obj(:).^2);
else
    grad = sparse(row, col, val, size(D,1), size(D,2));
    
    [U, V, obj, iter] = localopt(U, V, row, col, val, size(D, 1), size(D, 2)...
        , 0, grad );
    
    theta = eye(size(U, 2));
end

end

